package com.lkd.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.lkd.common.VMSystem;
import com.lkd.config.TopicConfig;
import com.lkd.contract.VendoutContract;
import com.lkd.contract.VendoutData;
import com.lkd.dao.OrderDao;
import com.lkd.emq.MqttProducer;
import com.lkd.exception.LogicException;
import com.lkd.feign.UserService;
import com.lkd.vo.*;
import com.lkd.entity.OrderEntity;
import com.lkd.feign.VMService;
import com.lkd.service.OrderService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.util.concurrent.*;
import java.util.function.Supplier;

@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private VMService vmService;

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MqttProducer mqttProducer;


    @Override
    public OrderEntity getByOrderNo(String orderNo) {
        QueryWrapper<OrderEntity> qw = new QueryWrapper<>();
        qw.lambda()
                .eq(OrderEntity::getOrderNo, orderNo);
        return this.getOne(qw);
    }

    ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
            .setNameFormat("demo-pool-%d").build();

    //Common Thread Pool
    ExecutorService executorService = new ThreadPoolExecutor(10, 10,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());


    @Override
    public OrderEntity createOrderTask(PayVO payVO) throws ExecutionException, InterruptedException {

        String redisKey = "order_" + payVO.getInnerCode() + "_" + payVO.getSkuId();

        Boolean hasKey = redisTemplate.hasKey(redisKey);

        if (hasKey == null || hasKey) {
            throw new LogicException("当前系统繁忙，请稍后重试");
        }

        redisTemplate.opsForValue().set(redisKey, 1, Duration.ofSeconds(60));

        Boolean aBoolean = vmService.hasCapacity(payVO.getInnerCode(), Long.valueOf(payVO.getSkuId()));
        if (!aBoolean) {
            throw new LogicException("当前商品无库存，请勿下单");
        }

        //查询售货机信息 -- 开启异步线程
        CompletableFuture<VmVO> vmVOCompletableFuture = CompletableFuture.supplyAsync(new Supplier<VmVO>() {
            @Override
            public VmVO get() {
                return vmService.getVMInfo(payVO.getInnerCode());
            }
        },executorService);

        //查询售货机信息 -- 开启异步线程
        CompletableFuture<SkuVO> skuVOCompletableFuture = CompletableFuture.supplyAsync(() -> {
            return vmService.getSku(payVO.getSkuId());
        },executorService);

//        //查询售货机信息
//        VmVO vmInfo = vmService.getVMInfo(payVO.getInnerCode());
//        //查询商品信息
//        SkuVO sku = vmService.getSku(payVO.getSkuId());

        VmVO vmVO = vmVOCompletableFuture.get();
        SkuVO skuVO = skuVOCompletableFuture.get();

        //创建订单
        OrderEntity order = initOrderTask(payVO,vmVO,skuVO);

        return order;
    }

    @Override
    public void vendOut(OrderEntity orderEntity) {

        try {
            VendoutContract vendoutContract = new VendoutContract();
            vendoutContract.setInnerCode(orderEntity.getInnerCode());
            VendoutData vendoutData = new VendoutData();
            vendoutData.setOrderNo(orderEntity.getOrderNo());
            vendoutData.setSkuId(orderEntity.getSkuId());
            vendoutContract.setVendoutData(vendoutData);
            mqttProducer.send(TopicConfig.VMS_VENDOUT_TOPIC, 2, vendoutContract);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    private OrderEntity initOrderTask(PayVO payVO, VmVO vmInfo, SkuVO sku) {

        //查询合作商信息
        PartnerVO partner = userService.getPartner(vmInfo.getOwnerId());


        OrderEntity order = new OrderEntity();

        order.setOrderNo(System.nanoTime() + "");
        order.setInnerCode(payVO.getInnerCode());
        order.setAddr(vmInfo.getNodeAddr());
        order.setSkuId(sku.getSkuId());
        order.setSkuName(sku.getSkuName());
        order.setClassId(sku.getClassId());
        order.setStatus(VMSystem.ORDER_STATUS_CREATE);
        order.setAmount(sku.getRealPrice());
        order.setPrice(sku.getPrice());
        order.setPayType("2");
        order.setPayStatus(VMSystem.PAY_STATUS_NOPAY);

        order.setNodeId(vmInfo.getNodeId());
        order.setNodeName(vmInfo.getNodeName());
        order.setRegionId(vmInfo.getRegionId());
        order.setRegionName(vmInfo.getRegionName());
        order.setBusinessId(vmInfo.getBusinessId());
        order.setBusinessName(vmInfo.getBusinessName());
        order.setOwnerId(vmInfo.getOwnerId());
        order.setOpenId(payVO.getOpenId());

        //分账金额
        BigDecimal decimal = new BigDecimal(sku.getRealPrice());
        BigDecimal bigDecimal = new BigDecimal(partner.getRatio());
        BigDecimal multiply = decimal.multiply(bigDecimal);
        BigDecimal divide = multiply.divide(new BigDecimal(100), RoundingMode.HALF_UP);

        order.setBill(divide.intValue());

        this.save(order);
        return order;
    }

}
